package com.pb.wkflow.core.factor.behavior;

import com.pb.infra.oth.util.SpringContextUtil;
import com.pb.wkflow.api.entity.ParticipantUserEntity;
import com.pb.wkflow.api.exception.ApprovalException;
import com.pb.wkflow.core.camunda.bpmn.instance.Participants;
import com.pb.wkflow.core.camunda.bpmn.instance.UserParticipant;
import com.pb.wkflow.core.camunda.bpmn.instance.VoteWork;
import com.pb.wkflow.core.entity.PostInfo;
import com.pb.wkflow.core.service.UserParticipantService;
import com.pb.wkflow.core.service.WorkflowService;
import com.pb.wkflow.core.utils.ArrayUtils;
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.engine.impl.persistence.entity.TaskEntity;
import org.camunda.bpm.engine.impl.pvm.delegate.ActivityExecution;
import org.camunda.bpm.model.bpmn.instance.UserTask;
import org.camunda.bpm.model.xml.instance.ModelElementInstance;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.pb.wkflow.core.config.Constants.VOTE_WORK_COLLECTION;

/**
 * 默认会签解析行为
 * @author 苗益辉
 * @date 2022/5/18 9:24
 */
@Slf4j
@Service
public class DefaultMultiInstanceActivityBehavior {

    public void defaultExecute(ActivityExecution execution) {
        WorkflowService workflowService = SpringContextUtil.getBean(WorkflowService.class);
        ModelElementInstance modelElementInstance = execution.getBpmnModelInstance().getModelElementById(execution.getCurrentActivityId().split("#")[0]);
        if(!(modelElementInstance instanceof UserTask)) {
            return;
        }
        UserTask userTask = (UserTask) modelElementInstance;
        UserParticipant userParticipant = userTask.getExtensionElements().getElementsQuery().filterByType(UserParticipant.class).singleResult();
        VoteWork voteWork = userTask.getExtensionElements().getElementsQuery().filterByType(VoteWork.class).singleResult();
        String participantType = userParticipant.getParticipantType();
        String allocation = voteWork.getAllocation();
        TaskEntity taskEntity = this.executeTask(execution);
        if(UserParticipant.CONFIG_TYPE_1.equals(participantType)) {
            List<PostInfo> postInfos = workflowService.getParticipantType1(userParticipant, taskEntity);
            setCollection(execution, postInfos, allocation);
        }else if (UserParticipant.CONFIG_TYPE_3.equals(participantType)) {
            Set<String> userIds = workflowService.getParticipantType3(userParticipant, taskEntity);
            List<PostInfo> postInfos = new ArrayList<>();
            for(String userId : userIds) {
                PostInfo postInfo = PostInfo.builder()
                        .type(Participants.TYPE_USER)
                        .userId(userId).build();
                postInfos.add(postInfo);
            }
            execution.setVariable(VOTE_WORK_COLLECTION, postInfos);
        }else if (UserParticipant.CONFIG_TYPE_4.equals(participantType)) {
            List<PostInfo> postInfos = this.getParticipantType4(workflowService, userParticipant, taskEntity);
            setCollection(execution, postInfos, allocation);
        }else if (UserParticipant.CONFIG_TYPE_5.equals(participantType)) {
            List<PostInfo> postInfos = workflowService.getParticipantType5(userParticipant, taskEntity);
            setCollection(execution, postInfos, allocation);
        }
    }

    public TaskEntity executeTask(ActivityExecution execution) {
        TaskEntity taskEntity = new TaskEntity();
        taskEntity.setProcessInstanceId(execution.getProcessInstanceId());
        taskEntity.setProcessDefinitionId(execution.getProcessDefinitionId());
        taskEntity.setExecutionId(execution.getId());
        taskEntity.setVariables(execution.getVariables());
        return taskEntity;
    }

    public void setCollection(ActivityExecution execution, List<PostInfo> postInfos, String allocation) {
        if(VoteWork.ALLOCATION_BY_PARTICIPANT.equals(allocation)) {
            //按照参与者分配任务
            if(ArrayUtils.isEmpty(postInfos)) {
                throw new ApprovalException("参与者不能为空");
            }
            execution.setVariable(VOTE_WORK_COLLECTION, postInfos);
        }else if (VoteWork.ALLOCATION_BY_PROCESSOR.equals(allocation)) {
            UserParticipantService userParticipantService = SpringContextUtil.getBean(UserParticipantService.class);
            List<ParticipantUserEntity> userEntities = userParticipantService.findUserByParticipants(postInfos);
            //按照操作员个数领取工作项
            Set<String> userIds = userEntities.stream().map(ParticipantUserEntity::getUserId).collect(Collectors.toSet());
            postInfos = new ArrayList<>();
            for(String userId : userIds) {
                PostInfo postInfo = PostInfo.builder()
                        .type(Participants.TYPE_USER)
                        .userId(userId)
                        .build();
                postInfos.add(postInfo);
            }
            execution.setVariable(VOTE_WORK_COLLECTION, postInfos);
        }
    }

    public List<PostInfo> getParticipantType4(WorkflowService workflowService,UserParticipant userParticipant,
                                              TaskEntity taskEntity) {
        List<PostInfo> postInfos = new ArrayList<>();
        Object aboutDataValue = workflowService.getParticipantType4(userParticipant,taskEntity);
        if(aboutDataValue instanceof String) {
            PostInfo postInfo = PostInfo.builder()
                    .type(Participants.TYPE_USER)
                    .userId((String) aboutDataValue).build();
            postInfos.add(postInfo);
        }else if (aboutDataValue instanceof PostInfo) {
            postInfos.add((PostInfo) aboutDataValue);
        }else if (aboutDataValue instanceof List) {
            postInfos = (List<PostInfo>) aboutDataValue;
        }
        return postInfos;
    }
}
